package com.meilishuo.android.performance;

import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import org.testng.annotations.Test;

import java.io.*;
import java.math.BigDecimal;
import java.util.*;

/**
 * Created by Xuemeng Wang on 15/3/10.
 * 解析抓取到的cpu信息，转换成用电消耗
 */
public class BatteryInfo {
    private static final String cpuBaseDir="target/android-info/battery";
    private static final String cpuDatDir="target/android-info/battery/dat";
    private static final String cpuFreqFile = "target/android-info/battery/dat/cpufreq.dat";
    private static final String power_Dir = "src/main/resources";
    private static final String htmlDir = "target/android-info/battery/html";
    private static final String processFile = "target/android-info/battery/dat/process.pid";
    private static final String runInfo = "target/android-info/run-info.txt";
    private static final String jpgFile = "target/android-info/battery/html/battery.jpg";
    private static final String url = "http://agile.meiliworks.com/data_mgr/save/dashboard";

    private static List<Double> batteryList = new ArrayList<Double>(); //存放某个app所有进程的cpu消耗

    /**
     * 计算cpu每秒消耗在美丽说进程上的时间片段
     */
    public static void caculateCpuTimePerSec()
    {
        File dirFile = new File(cpuDatDir);
        File[] cpustats = dirFile.listFiles(new FileFilter() {
            @Override
            public boolean accept(File pathname) {
                return pathname.getName().startsWith("cpustat-");
            }
        });


        Map<String, Double> cpuFreqMap = getCpuFreq();
        //Map<String, Double> cpuFreqBatteryMap = getCpuFreqBattery();

        int pos = 0; //第一次运行要把数据填充到batteryList中

        for(File fileIndex : cpustats)
        {
            Double totalBattery = 0.0;

            StringBuffer stringBuffer = new StringBuffer();
            System.out.println(fileIndex.getName());
            List<Integer> cpustatList = new ArrayList<Integer>();
            List<Double> batteryUsedPerList = new ArrayList<Double>();
            try {
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(fileIndex)));
                String line = null;

                int first = 0;
                while((line=bufferedReader.readLine())!=null)
                {
                    int sum = 0;
                    if("".equals(line.trim()))
                        continue;
                    String[] array = line.trim().split(" "); //空格分隔
                    for(String arrayIndex : array)
                    {
                        sum += Integer.parseInt(arrayIndex);
                    }
                    cpustatList.add(sum - first);
                    first = sum;
                }

                int count = 0;
                //将cpu时钟次数，转换成电量消耗
                for(int intIndex : cpustatList) {

                    Iterator iterator = cpuFreqMap.entrySet().iterator();
                    Double sumBattery = 0.0;
//                    while(iterator.hasNext())
//                    {
//                        Map.Entry entry = (Map.Entry)iterator.next();
//                        String cpuFreqKey = (String) entry.getKey();  //频率
//                        Double cpuFreqValue = (Double) entry.getValue(); //频率分布
//                        //Double cpuFreqBattery = cpuFreqBatteryMap.get(cpuFreqKey); //指定频率的单位时间耗电量
//                        //if(cpuFreqBattery == null)
//                          //  continue;
//                        //Double batteryUsed = intIndex * cpuFreqValue / Double.parseDouble(cpuFreqKey) * cpuFreqBattery;
//
//                        sumBattery += batteryUsed;
//                    }
                    //sumBattery /= 3600;

                    batteryUsedPerList.add(intIndex * 1.0);
//                    totalBattery += sumBattery;
                    count++;
                    if(count == 1)
                        continue;
                    totalBattery += intIndex;
                    if(pos==0)
                    {
                        batteryList.add(intIndex * 1.0);
                    }
                    else
                    {
                        if(count < batteryList.size())
                            batteryList.set(count, batteryList.get(count) + intIndex);
                    }
                }
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            batteryUsedPerList.add(0, totalBattery);  //第一个，存放耗电总量

            int start = fileIndex.getName().indexOf("cpustat-");
            int end = fileIndex.getName().lastIndexOf(".");
            String processName = getProcessByPid(fileIndex.getName().substring(start+"cpustat-".length(), end));

            writeHtml(htmlDir + File.separator + processName + ".html", batteryUsedPerList);

            pos++;
        }
    }

    /**
     * 获取android手机cpu各频率的时间分布
     */
    public static Map<String, Double> getCpuFreq()
    {
        Map<String, Double> cpuFreqMap = new HashMap<String, Double>();
        try {
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(cpuFreqFile)));
            String line = null;
            int totalTime = 0;
            while((line=bufferedReader.readLine())!=null)
            {
                String[] array = line.trim().split(" ");
                int timeSlice = Integer.parseInt(array[1]);
                cpuFreqMap.put(array[0], timeSlice/1.0);
                totalTime += Integer.parseInt(array[1]);
            }
            Iterator iter = cpuFreqMap.entrySet().iterator();
            while (iter.hasNext())
            {
                Map.Entry entry = (Map.Entry) iter.next();
                String key = (String) entry.getKey();
                Double value = (Double) entry.getValue();
                cpuFreqMap.put(key, value / totalTime);
            }
        } catch (Exception e)
        {
            e.printStackTrace();
        }

        return cpuFreqMap;
    }

    /**
     * 获取cpu不同频率下的耗电量
     */
    public static Map<String, Double> getCpuFreqBattery()
    {
        File file = new File(cpuBaseDir);
        File[] files = file.listFiles(new FileFilter() {
            @Override
            public boolean accept(File pathname) {
                return pathname.getName().endsWith(".device");
            }
        });
        String deviceId = files[0].getName();
        deviceId = deviceId.substring(0, deviceId.indexOf("."));

        Map<String, Double> cpuFreqBattery = new HashMap<String, Double>();
        BufferedReader bufferedReader = null;
        try{
            bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(power_Dir+File.separator+"power_profile_"+deviceId+".xml")));
            String line = null;

            boolean isKey = false;
            boolean isValue = false;

            List<String> speedList = new ArrayList<String>();
            List<Double> activeList = new ArrayList<Double>();
            while((line=bufferedReader.readLine())!=null)
            {
                if(!line.contains("cpu.speeds") && !isKey && !isValue)
                    continue;
                else {
                    if(!isValue)
                        isKey = true;
                }
                //System.out.println(line);
                //记录cpu频率
                if(line.contains("value") && isKey && !isValue)
                {
                    int start = line.indexOf("<value>");
                    int end = line.indexOf("</value>");
                    String value = line.substring(start+"<value>".length(), end);
                    speedList.add(value);
                }
                if(line.contains("cpu.active"))
                {
                    isKey = false;
                    isValue = true;
                }
                //记录cpu耗电量
                if(line.contains("value") && !isKey && isValue)
                {
                    int start = line.indexOf("<value>");
                    int end = line.indexOf("</value>");
                    String value = line.substring(start+"<value>".length(), end);
                    activeList.add(Double.parseDouble(value));

                }

            }
            int length = speedList.size();
            for(int i=0;i<length;i++)
            {
                cpuFreqBattery.put(speedList.get(i), activeList.get(i));
            }
        } catch (Exception e)
        {
            e.printStackTrace();
        }

        return cpuFreqBattery;
    }


    public static void writeHtml(String fileName, List<Double> valueList)
    {
        //写入xml
        File file = new File(fileName);
        try {
            BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file, true), "UTF-8"));
            bufferedWriter.write("<html>\n" +
                    "<head>\n" +
                    "<meta charset=\"UTF-8\" />" +
                    "<title>JSChart</title>\n" +
                    "\n" +
                    "<script type=\"text/javascript\" src=\"http://www.jscharts.com/script/jscharts.js?v=3.0\"></script>\n" +
                    "\n" +
                    "</head>\n" +
                    "<body>\n" +
                    "<h3>总消耗电量:"+valueList.get(0)+"mAh</h3>\n" +
                    "\n" +
                    "<div id=\"graph\">Loading graph...</div>\n" +
                    "\n" +
                    "<script type=\"text/javascript\">\n");
            bufferedWriter.flush();
            StringBuffer stringBuffer = new StringBuffer();
            stringBuffer.append("var myData = new Array(");
            int pos = 1;
            for(Double index : valueList)
            {
                //去掉第一行
                if(pos == 1 || pos ==2) {
                    pos++;
                    continue;
                }
                BigDecimal bigDecimal = new BigDecimal(index);
                String result = bigDecimal.toString();
                stringBuffer.append("[" + pos + ", " + result + "],");
                pos++;
            }
            System.out.println(stringBuffer.toString());
            int startPos = stringBuffer.lastIndexOf(",");
            if(startPos==-1)
            {
                stringBuffer.append(")");
            }
            else {
                stringBuffer.replace(startPos, stringBuffer.length(), ");");
            }
            bufferedWriter.write(stringBuffer.toString());
            bufferedWriter.write("var myChart = new JSChart('graph', 'line');\n" +
                    "        myChart.setDataArray(myData);\n" +
                    "        myChart.setLineColor('#8D9386');\n" +
                    "        myChart.setLineWidth(4);\n" +
                    "        myChart.setTitleColor('#7D7D7D');\n" +
                    "        myChart.setAxisColor('#9F0505');\n" +
                    "        myChart.setGridColor('#a4a4a4');\n" +
                    "        myChart.setAxisValuesColor('#333639');\n" +
                    "        myChart.setAxisNameColor('#333639');\n" +
                    "        myChart.setTextPaddingLeft(0);\n" +
                    "        myChart.setBarSpeed(100);\n" +
                    "        myChart.setLineSpeed(100);\n" +
                    "        myChart.setSize(800, 400);\n" +
                    "        myChart.draw();\n" +
                    "\n" +
                    "</script>\n" +
                    "\n" +
                    "</body>\n" +
                    "</html>");
            bufferedWriter.flush();
            bufferedWriter.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static String getProcessByPid(String pid)
    {
        File file = new File(processFile);
        try {
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
            String line = null;
            while ((line=bufferedReader.readLine())!=null) {
                if(!line.startsWith(pid))
                    continue;
                String[] result = line.split(" ");
                int start = result[1].lastIndexOf("/") == -1 ? 0 : result[1].lastIndexOf("/");
                return result[1].substring(start, result[1].length());
            }
        } catch (Exception e)
        {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 计算出最大值，最小值，平均值，然后推送到服务器
     */
    public void pushInfo2Server()
    {
        String sceneInfo = null;
        String startTime = null;
        String endTime = null;
        //读取运行信息
        File file = new File(runInfo);
        try {
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
            sceneInfo = bufferedReader.readLine(); //第一行场景信息，monkey，静置等
            startTime = bufferedReader.readLine();  //第二行开始运行时间
            endTime = bufferedReader.readLine();  //第三行结束运行时间

        } catch (Exception e)
        {
            e.printStackTrace();
        }

        //循环求最大值，最小值，平均值
        Double batteryMin = 10000.0;
        Double batteryMax = 0.0;
        Double sum = 0.0;
        for(Double index : batteryList)
        {
            sum += index;
            if(batteryMin > index)
                batteryMin = index;
            if(batteryMax < index)
                batteryMax = index;
        }

        //生成图标
        JFreeChartUtil.generateChart(batteryList, jpgFile);

        //将图片推送到tomcat上
        String relativelyPath=System.getProperty("user.dir");
        String jpgFilePath = relativelyPath+File.separator+jpgFile;
        System.out.println(jpgFilePath);
        System.out.println(relativelyPath + File.separator + "src"+ File.separator + "main" + File.separator + "resources" + File.separator +"scp.sh ");
        String result = ShellUtil.execShellFile(relativelyPath + File.separator + "src"+ File.separator + "main" + File.separator + "resources" + File.separator +"scp.sh ", jpgFilePath);
        System.out.println(result);

        Double avg = sum / batteryList.size();

        HttpClient httpClient = HttpClients.createDefault();
        try {

            //StringEntity stringEntity = new StringEntity("data=%7B%27max%27%3A+"+batteryMax+"%2C+%27avg%27%3A+"+avg+"%2C+%27pic%27%3A+%27%2Fhome%2Fwork%2Fpic.jpg%27%2C+%27min%27%3A+"+batteryMin+"%7D&runStartTime="+startTime+"&runEndTime="+endTime+"&type=POWER&scene="+sceneInfo+"&env=MOB");
            StringEntity stringEntity = new StringEntity("{\"env\":\"MOB\", \"type\":\"POWER\", \"scene\":\""+sceneInfo+"\", \"runStartTime\":\""+startTime+"\", \"runEndTime\":\""+endTime+"\", \"data\":{\"max\":"+batteryMax+", \"min\":"+batteryMin+", \"avg\":"+avg+", \"pic\":\""+Constant.tomcatUrl+"/battery.jpg"+"\"}}", "utf-8");
            System.out.println(EntityUtils.toString(stringEntity));
            HttpPost post = new HttpPost(url);
            post.addHeader(HTTP.CONTENT_TYPE, "application/x-www-form-urlencoded");
            post.setEntity(stringEntity);

            HttpResponse response = httpClient.execute(post);
            System.out.println(EntityUtils.toString(response.getEntity()));
            post.releaseConnection();

        } catch (Exception e)
        {
            e.printStackTrace();
        }


    }

    @Test
    public void testBattery()
    {
        caculateCpuTimePerSec();
        pushInfo2Server();
    }

}
